import 'dart:io';
import 'package:dio/dio.dart';
import 'package:base_plugin/base_plugin.dart';
import 'package:finance_app/src/common/config.dart';
import 'package:finance_app/src/common/prevent_repeated_event.dart';
import 'package:finance_app/src/entities/expense_detail_entity.dart';
import 'package:finance_app/src/entities/suggest_date_entity.dart';
import 'package:finance_app/src/http_service/http_common_service.dart';
import 'package:finance_app/src/http_service/http_setting_service.dart';
import 'package:finance_app/src/provider/dashboard/contact/business_contact_detail_provider.dart';
import 'package:finance_app/src/provider/dashboard/contact/detail/contact_detail_transaction_provider.dart';
import 'package:finance_app/src/provider/dashboard/credit_debit/credit_debit_provider.dart';
import 'package:finance_app/src/provider/dashboard/credit_debit/views/credit_note_provider.dart';
import 'package:finance_app/src/provider/dashboard/credit_debit/views/debit_note_provider.dart';
import 'package:finance_app/src/provider/dashboard/dashboard_transactions_provider.dart';
import 'package:finance_app/src/provider/dashboard/purchase/purchases_provider.dart';
import 'package:finance_app/src/provider/dashboard/purchase/views/purchases_bill_provider.dart';
import 'package:finance_app/src/provider/dashboard/purchase/views/purchases_expense_provider.dart';
import 'package:finance_app/src/provider/dashboard/purchase/views/purchases_po_provider.dart';
import 'package:finance_app/src/provider/dashboard/purchase/views/purchases_summary_provider.dart';
import 'package:finance_app/src/provider/dashboard/sales/sales_provider.dart';
import 'package:finance_app/src/provider/dashboard/sales/views/sales_invoice_provider.dart';
import 'package:finance_app/src/provider/dashboard/sales/views/sales_quotation_provider.dart';
import 'package:finance_app/src/provider/dashboard/sales/views/sales_summary_provider.dart';
import 'package:finance_app/src/provider/dashboard/transaction/all_transactions_provider.dart';
import 'package:finance_app/src/provider/dashboard_provider.dart';
import 'package:finance_app/src/provider/dashboard/dashboard_view_provider.dart';
import 'package:finance_app/src/provider/hr_payroll/hr_and_payroll_provider.dart';
import 'package:finance_app/src/provider/hr_payroll/views/reimburse_provider.dart';
import 'package:finance_app/src/router_gen/override_route_providers.dart';
import 'package:finance_app/src/router_gen/router_gen_providers.dart';
import 'package:finance_app/src/utils/file_utils.dart';
import 'package:finance_app/src/utils/permission_utils.dart';
import 'package:finance_app/src/widgets/bottom_sheet/delete_info_bottom_sheet.dart';
import 'package:flutter/material.dart';
import 'package:share/share.dart';

mixin InitEditDataMixin<T> on BaseProvider<T> {
  int id;

  bool isEdit;

  String get type;

  DateTime date;

  PreventRepeatedEvent _event = PreventRepeatedEvent();

  bool numberHasError = false;

  void init(int id) {
    this.id = id;
    isEdit = false;
  }

  @override
  void initState() {
    super.initState();
    if (id == null) {
      loadSuggestNumber();
      loadSuggestDate();
    }
  }

  @override
  void dispose() {
    _event?.dispose();
    super.dispose();
  }

  @override
  Future get dataFuture => id == null ? null : editDataFuture;

  Future get editDataFuture;

  CancelToken cancelToken = CancelToken();

  void onShare() async {
    if (type == null || id == null) return;
    File file;
    obtainContext?.call((context) async {
      BaseConfig.dialogBase
          .showLoadingDialog(context: context, text: 'loading...');
      file = await FileUtils.getPdfFile(type, id,
          cancelToken: cancelToken,
          onReceiverProgress: (int count, int total) {});
      Navigator.of(context).pop();
      if (file != null) {
        FileUtils.openFile(file);
      }
    });
  }

  void onChangeEditMode() {
    if (Config.currentSubscription.flag == 1) {
      obtainContext?.call((context) async {
        if (Config.currentSubscription.isTrial == 1) {
          showTrialHasExpiredBottomSheet(context);
        } else {
          showSubscriptionExpiredBottomSheet(context);
        }
      });
      return;
    }
    isEdit = !isEdit;
    update();
  }

  TextEditingController get numberCtl;

  var listener;

  void _eventDispose() {
    _event?.cancel();
    if (listener != null) {
      numberCtl.removeListener(listener);
    }
  }

  int get parentAccountId => null;

  void loadSuggestNumber() async {
    numberCtl?.text = " ";
    _eventDispose();
    if (numberCtl != null && type != null)
      await post(HttpCommonService.suggestNumber(type, parentAccountId),
          onSuccess: (result) {
        final number = getEntityFromResult<String>(result);
        if (numberCtl != null) {
          numberCtl.text = number;
        }
        listener = () {
          _event.sendEvent(numberCtl.text);
        };
        numberCtl.addListener(listener);
        _event.addEventListener(_handleInput);
      });
  }

  void loadSuggestDate() async {
    if (type == null) return;
    if (date == null)
      await post(HttpSettingService.getSuggestTime(type), onSuccess: (result) {
        SuggestDateEntity suggestDateEntity =
            getEntityFromResult<SuggestDateEntity>(result);
        final dateString = suggestDateEntity.typeDate ??
            suggestDateEntity.financialYearDate.start;
        date = DateTime.tryParse(dateString).toLocal() ?? DateTime.now();
        update();
      });
  }

  void _handleInput(searchData) {
    if (searchData.isNotEmpty)
      post(HttpCommonService.numberExist(type, searchData),
          onSuccess: (result) {
        int hasExist = result.data['data'];
        print('hasExist:$hasExist');
        if (hasExist == 1) {
          numberHasError = true;
        } else {
          numberHasError = false;
        }
        update();
      });
  }

  void handleDataUpdate(T t) {
    try {
      Config.dashboardProvider
          ?.getChildProvider<DashboardViewProvider>()
          ?.getChildProvider<DashboardTransactionsProvider>()
          ?.updateTapDetailItem(t);
    } catch (e) {}

    Providers.get<AllTransactionsProvider>(
            RouterGenProviders.allTransactionsPage, null)
        ?.updateTapDetailItem(t);
    Providers.get<PurchasesProvider>(RouterGenProviders.purchasesPage, null)
        ?.getChildProvider<PurchasesSummaryProvider>()
        ?.updateTapDetailItem(t);

    Providers.get<PurchasesProvider>(RouterGenProviders.purchasesPage, null)
        ?.getChildProvider<PurchasesPoProvider>()
        ?.updateTapDetailItem(t);

    Providers.get<PurchasesProvider>(RouterGenProviders.purchasesPage, null)
        ?.getChildProvider<PurchasesBillProvider>()
        ?.updateTapDetailItem(t);

    Providers.get<PurchasesProvider>(RouterGenProviders.purchasesPage, null)
        ?.getChildProvider<PurchasesExpenseProvider>()
        ?.updateTapDetailItem(t);

    Providers.get<SalesProvider>(RouterGenProviders.salesPage, null)
        ?.getChildProvider<SalesSummaryProvider>()
        ?.updateTapDetailItem(t);

    Providers.get<SalesProvider>(RouterGenProviders.salesPage, null)
        ?.getChildProvider<SalesQuotationProvider>()
        ?.updateTapDetailItem(t);

    Providers.get<SalesProvider>(RouterGenProviders.salesPage, null)
        ?.getChildProvider<SalesInvoiceProvider>()
        ?.updateTapDetailItem(t);

    Providers.get<CreditDebitProvider>(RouterGenProviders.creditDebitPage, null)
        ?.getChildProvider<CreditNoteProvider>()
        ?.updateTapDetailItem(t);

    Providers.get<CreditDebitProvider>(RouterGenProviders.creditDebitPage, null)
        ?.getChildProvider<DebitNoteProvider>()
        ?.updateTapDetailItem(t);

    Providers.get<BusinessContactDetailProvider>(
            RouterGenProviders.businessContactDetailPage, null)
        ?.getChildProvider<ContactDetailTransactionProvider>()
        ?.updateTapDetailItem(t);

    if (t is ExpenseDetailEntity) {
      Providers.get<HrAndPayrollProvider>(
              RouterGenProviders.hrAndPayrollPage, null)
          ?.getChildProvider<ReimburseProvider>()
          ?.updateData(t);
      if (!Config.hasPermission(PermissionUtils.homeDashboard)) {
        Config.dashboardProvider
            ?.getChildProvider<HrAndPayrollProvider>()
            ?.getChildProvider<ReimburseProvider>()
            ?.updateData(t);
      }
    }
  }
}
